/*
 * Copyright (c) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License,Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.mylibrary.player.view;

import ohos.agp.components.Attr;
import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.components.Component.LayoutRefreshedListener;
import ohos.agp.components.DependentLayout;
import ohos.agp.components.surfaceprovider.SurfaceProvider;
import ohos.agp.graphics.Surface;
import ohos.agp.graphics.SurfaceOps;
import ohos.agp.window.service.WindowManager;
import ohos.app.Context;

import com.mylibrary.player.api.ImplPlayModule;
import com.mylibrary.player.api.ImplPlayer;
import com.mylibrary.player.constant.Constants;
import com.mylibrary.player.util.CommonUtils;

import java.util.Optional;

/**
 * UniversalVideoView
 *
 * @since 2021-7-08
 */
public class UniversalVideoView extends DependentLayout implements ImplPlayModule, LayoutRefreshedListener {
    private ImplPlayer player;
    private SurfaceProvider surfaceView;
    private Surface surface;
    private boolean isTopPlay;
    private int viewWidth;
    private int viewHeight;
    private UniversalMediaController mMediaController;
    private boolean mFitXY;

    /**
     * constructor of PlayerView
     *
     * @param context context
     */
    public UniversalVideoView(Context context) {
        this(context, null);
    }

    /**
     * constructor of PlayerView
     *
     * @param context context
     * @param attrSet attSet
     */
    public UniversalVideoView(Context context, AttrSet attrSet) {
        this(context, attrSet, null);
    }

    /**
     * constructor of PlayerView
     *
     * @param context context
     * @param attrSet attSet
     * @param styleName styleName
     */
    public UniversalVideoView(Context context, AttrSet attrSet, String styleName) {
        super(context, attrSet, styleName);
        WindowManager.getInstance().getTopWindow().get().setTransparent(true); // 不设置窗体透明会挡住播放内容，除非设置pinToZTop为true
        if (attrSet != null) {
            mFitXY = CommonUtils.getBooleanValue(attrSet, "uvv_fitXY", false);
        }
        if (attrSet != null) {
            Optional<Attr> optIsTopPlay = attrSet.getAttr("top_play");
            optIsTopPlay.ifPresent(attr -> isTopPlay = "true".equals(attr.getStringValue()));
        }
        initView();
        initListener();
        setLayoutRefreshedListener(this);
    }

    private void initView() {
        surfaceView = new SurfaceProvider(mContext);
        LayoutConfig layoutConfig = new LayoutConfig();
        layoutConfig.addRule(LayoutConfig.CENTER_IN_PARENT);
        surfaceView.setLayoutConfig(layoutConfig);
        surfaceView.pinToZTop(isTopPlay);
        addComponent(surfaceView);
    }

    private void initListener() {
        surfaceView.getSurfaceOps().ifPresent(surfaceOps -> surfaceOps.addCallback(new SurfaceOps.Callback() {
            @Override
            public void surfaceCreated(SurfaceOps surfaceOps) {
                surface = surfaceOps.getSurface();
                if (player != null) {
                    player.addSurface(surface);
                }
            }

            @Override
            public void surfaceChanged(SurfaceOps surfaceOps, int info, int width, int height) {
            }

            @Override
            public void surfaceDestroyed(SurfaceOps surfaceOps) {
            }
        }));
        surfaceView.setClickedListener(new ClickedListener() {
            @Override
            public void onClick(Component component) {
                mMediaController.handlerControllerVisibility();
            }
        });
    }

    private void updateVideoSize(double videoScale) {
        if (surfaceView == null) {
            initView();
        }
        if (videoScale > 1) {
            surfaceView.setHeight(viewHeight);
            int viewWidth = (int) (viewHeight * videoScale);
            surfaceView.setWidth(viewWidth);
        } else {
            surfaceView.setHeight(viewHeight);
            surfaceView.setWidth((int) Math.min(viewHeight * videoScale, viewWidth));
        }
    }

    /**
     * bind bind player
     *
     * @param implPlayer implPlayer
     */
    @Override
    public void bind(ImplPlayer implPlayer) {
        this.player = implPlayer;
        this.player.addPlayerViewCallback((width, height) -> mContext.getUITaskDispatcher().asyncDispatch(() -> {
            if (width > 0) {
                setWidth(width);
            }
            if (height > 0) {
                setHeight(height);
            }
        }));
    }

    /**
     * unbind unbind player
     */
    @Override
    public void unbind() {
        surfaceView.removeFromWindow();
        surfaceView = null;
        surface = null;
    }

    /**
     * onRefreshed
     *
     * @param component view
     */
    @Override
    public void onRefreshed(Component component) {
        int newWidth = component.getWidth();
        int newHeight = component.getHeight();
        double videoScale = player.getVideoScale();
        if (videoScale != Constants.NUMBER_NEGATIVE_1 && (newWidth != viewWidth || newHeight != viewHeight) && !mFitXY) {
            viewWidth = newWidth;
            viewHeight = newHeight;
            mContext.getUITaskDispatcher().asyncDispatch(() -> updateVideoSize(videoScale));
        }
    }

    /**
     * setMediaController 绑定controlView
     *
     * @param controllerView controllerView
     */
    public void setMediaController(UniversalMediaController controllerView) {
        this.mMediaController = controllerView;
    }
}
